﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace Hallenberg.SmartClient.Menu
{
    /// <summary>
    /// The ChildMenuItemsCollection class contains a list of child menu items for a menu item.
    /// The collection does not accept empty (null) items and provides simple functionality
    /// to retrieve indicies of items as well as indexing functionality. As expected of a collection
    /// it supports the IEnumerable interface.
    /// </summary>
    public class ChildMenuItemsCollection : IEnumerable<MenuItem>
    {
        private List<MenuItem> m_ChildItems = new List<MenuItem>();

        /// <summary>
        /// Add a new menu item to the collection.
        /// </summary>
        /// <param name="baseMenuItem">A valid menu item.</param>
        /// <exception cref="System.ArgumentNullException">Thrown if provided baseMenuItem is null.</exception>
        public void Add(MenuItem menuItem)
        {
            Debug.Assert(menuItem != null);
            if (menuItem == null)
            {
                throw new ArgumentNullException("menuItem");
            }

            m_ChildItems.Add(menuItem);
        }

        /// <summary>
        /// Returns the item at the position indicated by index.
        /// </summary>
        /// <param name="index">The index from which to retrieve an item from the collection.</param>
        /// <returns>The item at position 'index'.</returns>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if index is out of range.</exception>
        public MenuItem this[int index]
        {
            get
            {
                if (index < 0 || index > m_ChildItems.Count - 1)
                {
                    throw new ArgumentOutOfRangeException("index");
                }

                return m_ChildItems[index];
            }
        }

        /// <summary>
        /// Method returns the index of the menu item reference provided.
        /// </summary>
        /// <param name="menuItem">A valid object.</param>
        /// <returns>The menu item's index in the collection or -1 of not a part of the collection.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if provided menuItem parameter is null.</exception>
        public int IndexOf(MenuItem menuItem)
        {
            Debug.Assert(menuItem != null);
            if (menuItem == null)
            {
                throw new ArgumentNullException("menuItem");
            }

            return m_ChildItems.IndexOf(menuItem);
        }

        /// <summary>
        /// Method inserts a menu item at the provided index. 
        /// If index equals the number of items in the collection, this method works like Add".
        /// </summary>
        /// <param name="index">The position at which to insert the menu item in the collection.</param>
        /// <param name="menuItem">A valid menu item object.</param>
        /// <exception cref="System.ArgumentOutOfRangeException">Thrown if index is less than zero or greater than the number of items in the collection.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown if menuItem is null.</exception>
        public void Insert(int index, MenuItem menuItem)
        {
            Debug.Assert(index >= 0);
            Debug.Assert(index <= m_ChildItems.Count);

            if (index < 0 || index > m_ChildItems.Count)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            Debug.Assert(menuItem != null);

            if (menuItem == null)
            {
                throw new ArgumentNullException("menuItem");
            }

            m_ChildItems.Insert(index, menuItem);
        }

        /// <summary>
        /// This method sorts the items in the collection based on their SortIndex value.
        /// </summary>
        public void Sort()
        {
            m_ChildItems.Sort((left, right) => left.SortIndex.CompareTo(right.SortIndex));
        }

        /// <summary>
        /// Returns a new enumerator to iterate over the collection.
        /// </summary>
        /// <returns>A new enumerator instance.</returns>
        public IEnumerator<MenuItem> GetEnumerator()
        {
            return new MenuItemIterator(m_ChildItems);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new MenuItemIterator(m_ChildItems);
        }

        public int Count
        {
            get { return this.Count(); }
        }
        
    }
}
